package com.gitee.loocao.boot.enjoy.autoconfigure;

import com.jfinal.template.Engine;
import com.jfinal.template.ext.spring.JFinalViewResolver;
import com.jfinal.template.source.ClassPathSourceFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.*;
import org.springframework.boot.autoconfigure.template.TemplateLocation;
import org.springframework.boot.autoconfigure.web.ConditionalOnEnabledResourceChain;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.resource.ResourceUrlEncodingFilter;

import javax.annotation.PostConstruct;
import javax.servlet.Servlet;

@Configuration
@ConditionalOnClass({Engine.class})
@AutoConfigureAfter(WebMvcAutoConfiguration.class)
@EnableConfigurationProperties(EnjoyProperties.class)
public class EnjoyAutoConfiguration {
    private static final Log logger = LogFactory.getLog(EnjoyAutoConfiguration.class);

    private final ApplicationContext applicationContext;

    private final EnjoyProperties properties;

    public EnjoyAutoConfiguration(ApplicationContext applicationContext, EnjoyProperties properties) {
        this.applicationContext = applicationContext;
        this.properties = properties;
    }

    @PostConstruct
    public void checkTemplateLocationExists() {
        boolean checkTemplateLocation = this.properties.isCheckTemplateLocation();
        if (checkTemplateLocation) {
            TemplateLocation location = new TemplateLocation(this.properties.getPrefix());
            if (!location.exists(this.applicationContext)) {
                logger.warn("Cannot find template location: " + location
                        + " (please add some templates or check "
                        + "your Enjoy configuration)");
            }
        }
    }

    @Configuration
    @ConditionalOnNotWebApplication
    @EnableConfigurationProperties(EnjoyProperties.class)
    public static class EnjoyNonWebConfiguration {
        private final EnjoyProperties properties;

        public EnjoyNonWebConfiguration(EnjoyProperties properties) {
            this.properties = properties;
        }

        private void applyProperties(Engine engine) {
            engine.setBaseTemplatePath(this.properties.getBaseTemplatePath());
            // 是否热加载模板文件
            engine.setDevMode(this.properties.getDevMode());
            // 配置shared function，多文件用逗号分隔
            if (this.properties.getSharedFunction() != null) {
                for (String fileName : this.properties.getSharedFunction()) {
                    engine.addSharedFunction(fileName);
                }
            }
        }

        @Bean
        @ConditionalOnMissingBean
        public Engine engine() {
            Engine engine = new Engine();
            applyProperties(engine);
            return engine;
        }
    }

    @Configuration
    @ConditionalOnClass({Servlet.class})
    @ConditionalOnWebApplication
    @EnableConfigurationProperties(EnjoyProperties.class)
    public static class EnjoyWebConfiguration {
        private final EnjoyProperties properties;

        public EnjoyWebConfiguration(EnjoyProperties properties) {
            this.properties = properties;
        }

        @Bean
        @ConditionalOnMissingBean
        @ConditionalOnProperty(name = "jfinal.enjoy.enabled", matchIfMissing = true)
        public JFinalViewResolver enjoyViewResolver() {
            JFinalViewResolver resolver = new JFinalViewResolver();
            resolver.setSourceFactory(new ClassPathSourceFactory());
            this.properties.applyToViewResolver(resolver);
            resolver.setBaseTemplatePath(this.properties.getBaseTemplatePath());
            resolver.setDevMode(this.properties.getDevMode());
            if (this.properties.getSharedFunction() != null) {
                for (String fileName : this.properties.getSharedFunction()) {
                    resolver.addSharedFunction(fileName);
                }
            }
            resolver.setSessionInView(this.properties.getSessionInView());
            return resolver;
        }

        @Bean
        @ConditionalOnMissingBean
        @ConditionalOnEnabledResourceChain
        public ResourceUrlEncodingFilter resourceUrlEncodingFilter() {
            return new ResourceUrlEncodingFilter();
        }
    }

}
